package com.example.springbootfuture.futures;

import com.example.springbootfuture.factory.MyThreadFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;

import java.util.Objects;
import java.util.Random;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Function;

/**
 * @author: wukangrong
 * @date: 2020/8/28 14:46
 * @description:
 */
@Slf4j
public class Testss {

    private static ThreadFactory threadFactory = new CustomizableThreadFactory("springThread-pool-");


    private static ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 5,
            5L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(15), threadFactory);


    public static void main(String[] args) {

        // 有返回结果
        CompletableFuture f2 = CompletableFuture.runAsync(() -> {
            try {
                log.info("等待");
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },executor);
        // 有返回结果
        CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
            try {
                log.info("开始执行");
                Thread.sleep(1000);
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "zero";
        }, executor);
        CompletableFuture<String> f3 = CompletableFuture.supplyAsync(() -> "one", executor);
        // 等待两任务结束后对两结果进行处理
        CompletableFuture<String> result = f1.thenCombine(f3, (t, u) -> t + " " + u);
        result.thenAccept(log::info);
        log.info("到这");
        // 消费结果
        f1.thenAccept(e -> {
            if ("zero".equals(e)) {
                log.info("get result:"+e);
            } else {
                log.info("log");
            }
        });
        // 当之前的任务完成，不管结果如何继续执行
        f2.thenRun (() -> log.info("等待结束"));

        log.info("主线程结束");


        handle();
        whenComplete();
    }

    private static boolean flag = true;
    /**
     * 结果处理
     */
    public static void handle(){
        /*CompletableFuture<Integer> future = */CompletableFuture.supplyAsync(
                () -> {
                    if (flag) {
                        log.info("Handel");
                        throw new NullPointerException();
                    }
                    return new Random().nextInt(10);
                }, executor)
                .handle((param, throwable) -> {
                    int result = -1;
                    if (throwable == null) {
                        result = param * 2;
                    } else {
                        log.error("异常：{}",throwable.getMessage());
                    }
                    return result;
                });
    }

    public static void whenComplete() {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
            }
            if (new Random().nextInt() % 2 > 0) {
                int i = 12 / 0;
            }
            log.info("run end ...");
        }, executor);

        future.whenComplete((t, action) -> {
            if (Objects.isNull(action)) {
                log.info("执行完成！");
            } else {
                log.info("出粗：{}", action.getMessage());
            }
        });
    }

    /**
     * 通过allOf函数完成CountDownLatch功能
     * @throws InterruptedException
     */
    public static void doneCountDownLatch() throws InterruptedException {
        CompletableFuture c1 = CompletableFuture.runAsync(() -> {
            System.out.println(1);
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        CompletableFuture c2 = CompletableFuture.runAsync(() -> {
            System.out.println(2);
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        CompletableFuture c3 = CompletableFuture.runAsync(() -> {
            System.out.println(3);
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println(System.currentTimeMillis());
        CompletableFuture c4 = CompletableFuture.anyOf(c1, c2, c3);
        c4.whenComplete((t, ex) -> {
            System.out.println("over");
            System.out.println(System.currentTimeMillis());
        });
        TimeUnit.SECONDS.sleep(5);
    }
}

